package bl;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Arrays;

public class IntegersPublicParameters implements PublicParametersI {
	BigInteger G; // A prime number, represents the group Z*_G
	BigInteger q; // The order of the group G
	BigInteger g; // A generator for the group
	int bitLength;


	
	/**
	 * @param bitLength
	 * @throws Exception
	 * If the bitLengh parameter is not a positive number divided by 8.
	 */
	public IntegersPublicParameters(int bitLength) throws Exception {
		SecureRandom sr = new SecureRandom();
		if (bitLength % 8 != 0 || bitLength <= 0) {
			throw new Exception(
					"bitLength must be a positive number divided by 8.");
		}

		this.bitLength = bitLength;
		/*
		 * To make sure that in the BigIntegers in both the proof and the tokens
		 * bitLength/8 bytes will be enough (the MSB must be zero, and if in
		 * unsigned representation it should be 1, another byte is necessary).
		 */
		this.G = BigInteger.probablePrime(bitLength - 1, sr);
		this.q = this.G.subtract(BigInteger.ONE);

		do {
			this.g = new BigInteger(bitLength, sr);
		} while (this.g.compareTo(G) >= 0);
	}
	
	
	public IntegersPublicParameters(byte[] bytes) throws Exception {
		if (bytes.length % 3 != 0 || bytes.length == 0)
			throw new Exception(
					"The bytes array must be of a positive length divided by 3.");
 
		int third = bytes.length / 3;
		this.G = new BigInteger(Arrays.copyOfRange(bytes, 0, third));
		this.q = new BigInteger(Arrays.copyOfRange(bytes, third, 2*third));
		this.g = new BigInteger(Arrays.copyOfRange(bytes, 2*third, bytes.length));
		
		this.bitLength = third * 8;
	}
/*
	@Override
	public Object GetGroup() {
		return G;
	}

	@Override
	public BigInteger GetOrder() {
		return q;
	}

	@Override
	public Object GetGenerator() {
		return g;
	}
*/
	@Override
	public int GetTokenLengthBytes() {
		return bitLength / 8;
	}

	@Override
	public int GetProofLengthBytes() {
		return bitLength / 4;
	}

	@Override
	public int GetBitLength() {
		return bitLength;
	}

	@Override
	public byte[] GetBytes() {
		int byteLength = this.bitLength / 8;
		return Common.concat(	Common.CreatePaddedBigIntegerBytes(this.G, byteLength), Common.concat(	
								Common.CreatePaddedBigIntegerBytes(this.q, byteLength),
								Common.CreatePaddedBigIntegerBytes(this.g, byteLength)));
	}
	
	@Override
	public int GetPublicParametersLengthBytes() {
		return (this.bitLength * 3) / 8;
	}
}
